﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Collections;
using System.Reflection;
using UmlControlLibrary.Tools;
using UmlControlLibrary;

namespace UmlControlLibrary
{
    public class UmlClass : DiagramElement
    {

        public ObservableCollection<UmlProperty> PropertyList
        {
            get;
            set;
        }

        private void DeferredLoadProperties()
        {
            PropertyList.CollectionChanged -= new System.Collections.Specialized.NotifyCollectionChangedEventHandler(PropertyList_CollectionChanged);
            MethodList.CollectionChanged -= new System.Collections.Specialized.NotifyCollectionChangedEventHandler(MethodList_CollectionChanged);

            Type t = this.Metadata.Get<Type>("ClrType");

            BindingFlags flags = ///*BindingFlags.NonPublic |*/ BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
                                 BindingFlags.Instance | BindingFlags.Static |
            BindingFlags.Public  | BindingFlags.DeclaredOnly;

            IEnumerable<MemberInfo> members = t.GetProperties(flags).Cast<MemberInfo>();
            members = members.Union(t.GetFields(flags).Cast<MemberInfo>());
            foreach(MemberInfo member in members)
            {
                if (!member.Name.StartsWith("<"))
                    this.PropertyList.Add(new UmlProperty(member));
            }

            MethodInfo[] methods = t.GetMethods(//BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
                BindingFlags.Instance | BindingFlags.Static |
                BindingFlags.Public  | BindingFlags.DeclaredOnly);
            foreach (MethodInfo method in methods)
            {
                if (!method.IsSpecialName)
                    this.MethodList.Add(new UmlMethod(method));
            }
            this.Metadata["DeferredLoadingComplete"] = true;

            PropertyList.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(PropertyList_CollectionChanged);
            MethodList.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(MethodList_CollectionChanged);
        }

        public List<Object> PropertyListView
        {
            get
            {
                if ((this.Metadata.Get<bool>("DeferredLoading")) && (!this.Metadata.Get<bool>("DeferredLoadingComplete")))
                {
                    DeferredLoadProperties();
                }
                return PropertyGroupingHelper.Group(PropertyList.Cast<UmlMemberElement>());
            }
        }

        public ObservableCollection<UmlMethod> MethodList
        {
            get;
            set;
        }

        public List<Object> MethodListView
        {
            get
            {
                if ((this.Metadata.Get<bool>("DeferredLoading")) && (!this.Metadata.Get<bool>("DeferredLoadingComplete")))
                {
                    DeferredLoadProperties();
                }
                return PropertyGroupingHelper.Group(MethodList.Cast<UmlMemberElement>());
            }
        }



        public UmlClass(string className)
            : base(className)
        {
            PropertyList = new ObservableCollection<UmlProperty>();
            PropertyList.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(PropertyList_CollectionChanged);
            MethodList = new ObservableCollection<UmlMethod>();
            MethodList.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(MethodList_CollectionChanged);

            Metadata.Add("AllowUmlTreeviewDnd", true);
        }

        void PropertyList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            foreach (UmlProperty p in (sender as IEnumerable<UmlProperty>))
            {
                p.PropertyChanged -= new PropertyChangedEventHandler(PropertyListChanged);
                p.PropertyChanged += new PropertyChangedEventHandler(PropertyListChanged);
                p.Owner = this;
                //                UmlDiagram.Instance.CheckElement(p);
            }

            OnPropertyChanged("PropertyListView");
            OnPropertyChanged("Childs");
        }

        void PropertyListChanged(object sender, PropertyChangedEventArgs e)
        {
            OnPropertyChanged("PropertyListView");
            OnPropertyChanged("Childs");
        }

        void MethodList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            foreach (UmlMethod p in (sender as IEnumerable<UmlMethod>))
            {
                p.PropertyChanged -= new PropertyChangedEventHandler(MethodListChanged);
                p.PropertyChanged += new PropertyChangedEventHandler(MethodListChanged);
            }
            OnPropertyChanged("MethodListView");
            OnPropertyChanged("Childs");
        }

        void MethodListChanged(object sender, PropertyChangedEventArgs e)
        {
            OnPropertyChanged("MethodListView");
            OnPropertyChanged("Childs");
        }

        protected override ControlTemplate GetTemplate()
        {
            return DiagramElement.DiagramElementTemplateFactory(typeof(UmlClassControl));
        }

        public override ObservableCollection<UmlElement> GetChilds()
        {
            ObservableCollection<UmlElement> elements = base.GetChilds();
            foreach (UmlProperty property in PropertyList)
                elements.Add(property);
            foreach (UmlMethod property in MethodList)
                elements.Add(property);
            return elements;
        }

    }
}
